﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevelopStudio.Basic;
using SharpSvn;
using System.IO;
using CommonBasic = DevelopStudio.Common.Basic;
using CommonManage = DevelopStudio.Common.Manage;
using System.Diagnostics;

namespace DevelopStudio.Control.FormPage
{
    public partial class CheckModificationForm : Form
    {
        public bool ChangelistChanged { get; set; }

        protected List<SvnStatusEventArgs> UnControlChanges;

        protected WorkingCopyInfo workPlatform;

        public CheckModificationForm()
        {
            InitializeComponent();
            this.deleteToolStripMenuItem.Image = new Bitmap(Properties.Resources.Delete.ToBitmap(), new Size(16, 16));
            this.addToolStripMenuItem.Image = new Bitmap(Properties.Resources.Add.ToBitmap(), new Size(16, 16));
            this.explorerToToolStripMenuItem.Image = new Bitmap(Properties.Resources.Folder.ToBitmap(), new Size(16, 16));
        }

        private void CheckModificationForm_Load(object sender, EventArgs e)
        {
            this.comboBoxPlatform.DataSource = Utility.Settings.WorkingCopies;
            this.comboBoxPlatform.DisplayMember = "Path";
            this.comboBoxPlatform.ValueMember = "Path";

            if (this.comboBoxPlatform.Items.Count <= 0)
            {
                return;
            }

            this.comboBoxPlatform.SelectedIndex = 0;
            this.RefreshListView();
        }

        protected void RefreshListView()
        {
            this.UnControlChanges = Utility.GetUnControledFiles((string)this.comboBoxPlatform.SelectedValue);

            this.DisplayChanged();
        }

        protected void DisplayChanged()
        {
            if (this.UnControlChanges == null)
            {
                return;
            }

            if (this.workPlatform == null)
            {
                return;
            }

            this.listView1.Items.Clear();

            foreach (SvnStatusEventArgs var in this.UnControlChanges)
            {
                if (this.checkBoxIgnored.Checked == false)
                {
                    if (workPlatform.IgnoredList.Any(o => 
                        o.IgnoredType == (int)AppEnum.IgnoredType.Directory &&
                        var.FullPath.StartsWith(o.Value, StringComparison.OrdinalIgnoreCase) == true ||
                        o.IgnoredType == (int)AppEnum.IgnoredType.File &&
                        var.FullPath.Equals(o.Value, StringComparison.OrdinalIgnoreCase) == true ||
                        o.IgnoredType == (int)AppEnum.IgnoredType.Extention &&
                        Path.GetExtension(var.FullPath).Equals(o.Value, StringComparison.OrdinalIgnoreCase) == true
                        ) == true)
                    {
                        continue;
                    }
                }

                if (this.checkBoxUnversioned.Checked == false)
                {
                    if (var.LocalNodeStatus == SvnStatus.NotVersioned)
                    {
                        continue;
                    }
                }

                ListViewItem item = new ListViewItem(new string[] {
                var.FullPath.Replace(workPlatform.Path, ""),
                Path.GetExtension(var.Path),
                CommonManage.Utility.StatusDisplayName((CommonBasic.SvnStatus)var.LocalNodeStatus),
                var.Revision.ToString(),
                string.Empty
                });
                item.Tag = var;

                this.listView1.Items.Add(item);
            }
        }

        private void buttonRefresh_Click(object sender, EventArgs e)
        {
            this.RefreshListView();
        }

        private void checkBoxIgnored_CheckedChanged(object sender, EventArgs e)
        {
            this.DisplayChanged();
        }

        private void checkBoxUnversioned_CheckedChanged(object sender, EventArgs e)
        {
            this.DisplayChanged();
        }

        private void PrepareAddToIgnoredListToolStripMenuItem()
        {
            this.addToIgnoredListToolStripMenuItem.DropDownItems.Clear();

            List<ToolStripItem> stripItemList = new List<ToolStripItem>();

            if (this.listView1.SelectedItems.Count == 1)
            {
                SvnStatusEventArgs svnStatus = this.listView1.SelectedItems[0].Tag as SvnStatusEventArgs;

                if (svnStatus == null)
                {
                    return;
                }

                string extention = Path.GetExtension(svnStatus.FullPath);

                if (this.workPlatform.IgnoredList.Any(o => o.IgnoredType == (int)AppEnum.IgnoredType.Extention &&
                    o.Value.Equals(extention, StringComparison.OrdinalIgnoreCase)) == false)
                {
                    IgnoredItem ignoredItem = new IgnoredItem()
                    {
                        IgnoredType = (int)AppEnum.IgnoredType.Extention,
                        Value = extention
                    };

                    ToolStripMenuItem tempMenuItem = new ToolStripMenuItem()
                    {
                        Text = extention,
                        Tag = ignoredItem
                    };

                    stripItemList.Add(tempMenuItem);
                }

                string[] items = this.listView1.SelectedItems[0].SubItems[0].Text.Split(Path.DirectorySeparatorChar);

                string tempPath = string.Empty;
                string tempFullPath;
                int ignored;

                for (int i = 0; i < items.Length; i++)
                {
                    string var = items[i];

                    tempPath = Path.Combine(tempPath, var);

                    if (string.IsNullOrEmpty(tempPath) == true)
                    {
                        continue;
                    }

                    if (i == items.Length - 1)
                    {
                        ignored = (int)AppEnum.IgnoredType.File;
                    }
                    else
                    {
                        ignored = (int)AppEnum.IgnoredType.Directory;
                        tempPath += Path.DirectorySeparatorChar;
                    }

                    tempFullPath = Path.Combine(this.workPlatform.Path, tempPath);

                    if (this.workPlatform.IgnoredList.Any(o => o.IgnoredType == (int)AppEnum.IgnoredType.Extention &&
                        o.Value.Equals(extention, StringComparison.OrdinalIgnoreCase)) == false)
                    {
                        IgnoredItem ignoredItem = new IgnoredItem()
                        {
                            Value = tempFullPath,
                            IgnoredType = ignored
                        };

                        ToolStripMenuItem tempMenuItem = new ToolStripMenuItem()
                        {
                            Text = tempPath,
                            Tag = ignoredItem
                        };

                        stripItemList.Add(tempMenuItem);
                    }
                }

                foreach (ToolStripItem ignoredListToolStripItem in stripItemList)
                {
                    ignoredListToolStripItem.Click += ignoredListToolStripItem_Click;
                }

                if (stripItemList.Count <= 0)
                {
                    this.contextMenuStrip1.Items.Remove(this.addToIgnoredListToolStripMenuItem);
                }
                else
                {
                    this.addToIgnoredListToolStripMenuItem.DropDownItems.AddRange(stripItemList.ToArray());

                    if (this.contextMenuStrip1.Items.Contains(this.addToIgnoredListToolStripMenuItem) == false)
                    {
                        this.contextMenuStrip1.Items.Add(this.addToIgnoredListToolStripMenuItem);
                    }
                }
            }
            else
            {
                if (this.contextMenuStrip1.Items.Contains(this.addToIgnoredListToolStripMenuItem) == false)
                {
                    this.contextMenuStrip1.Items.Add(this.addToIgnoredListToolStripMenuItem);
                }
            }
        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            if (this.listView1.SelectedItems.Count <= 0)
            {
                e.Cancel = true;
            }

            this.contextMenuStrip1.Items.Clear();

            if (this.listView1.SelectedItems.Count == 1)
            {
                this.contextMenuStrip1.Items.Add(this.explorerToToolStripMenuItem);
            }

            #region Add And Remove

            bool add = true;
            bool delete = true;

            foreach (ListViewItem var in this.listView1.SelectedItems)
            {
                SvnStatusEventArgs svnStatus = var.Tag as SvnStatusEventArgs;

                if (svnStatus == null)
                {
                    continue;
                }

                if (svnStatus.LocalNodeStatus != SvnStatus.NotVersioned &&
                    add == true)
                {
                    add = false;
                }

                if (svnStatus.LocalNodeStatus != SvnStatus.Missing &&
                    delete == true)
                {
                    delete = false;
                }
            }

            if (add == false)
            {
                this.contextMenuStrip1.Items.Remove(this.addToolStripMenuItem);
            }
            else
            {
                if (this.contextMenuStrip1.Items.Contains(this.addToolStripMenuItem) == false)
                {
                    this.contextMenuStrip1.Items.Add(this.addToolStripMenuItem);
                }
            }

            if (delete == false)
            {
                this.contextMenuStrip1.Items.Remove(this.deleteToolStripMenuItem);
            }
            else
            {
                if (this.contextMenuStrip1.Items.Contains(this.deleteToolStripMenuItem) == false)
                {
                    this.contextMenuStrip1.Items.Add(this.deleteToolStripMenuItem);
                }
            }

            #endregion

            this.PrepareAddToIgnoredListToolStripMenuItem();

            this.contextMenuStrip1.Items.Add(this.moveToChangelistToolStripMenuItem);

            if (this.contextMenuStrip1.Items.Count <= 0)
            {
                e.Cancel = true;
                return;
            }
        }

        void ignoredListToolStripItem_Click(object sender, EventArgs e)
        {
            ToolStripItem toolStripItem = sender as ToolStripItem;

            if (toolStripItem == null)
            {
                return;
            }

            IgnoredItem ignoredItem = toolStripItem.Tag as IgnoredItem;

            if (ignoredItem == null)
            {
                return;
            }

            if (this.workPlatform.IgnoredList.Any(o => o.IgnoredType == ignoredItem.IgnoredType &&
                o.Value.Equals(ignoredItem.Value, StringComparison.OrdinalIgnoreCase)) == false)
            {
                this.workPlatform.IgnoredList.Add(ignoredItem);
            }

            Utility.SaveEnvironmentSettings();
            this.DisplayChanged();
        }

        private void addToIgnoredListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.listView1.SelectedItems.Count <= 1)
            {
                return;
            }

            foreach (ListViewItem var in this.listView1.SelectedItems)
            {
                SvnStatusEventArgs svnStatus = var.Tag as SvnStatusEventArgs;

                if (svnStatus == null)
                {
                    continue;
                }

                if (this.workPlatform.IgnoredList.Any(o => o.IgnoredType == (int)AppEnum.IgnoredType.File &&
                    o.Value.Equals(svnStatus.FullPath, StringComparison.OrdinalIgnoreCase)) == true)
                {
                    continue;
                }

                this.workPlatform.IgnoredList.Add(new IgnoredItem() { IgnoredType = (int)AppEnum.IgnoredType.File, Value = svnStatus.FullPath });
            }

            Utility.SaveEnvironmentSettings();
            this.DisplayChanged();
        }

        private void comboBoxPlatform_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.workPlatform = this.comboBoxPlatform.SelectedItem as WorkingCopyInfo;

            Process.Start("TortoiseProc.exe", @"/command:repostatus /path:" + this.workPlatform.Path + " /closeonend:0");
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                StringBuilder errorMessage = new StringBuilder();

                foreach (ListViewItem var in this.listView1.SelectedItems)
                {
                    SvnStatusEventArgs svnStatus = var.Tag as SvnStatusEventArgs;

                    if (svnStatus == null)
                    {
                        continue;
                    }

                    if (Utility.SvnClient.Add(svnStatus.FullPath) == false)
                    {
                        errorMessage.AppendLine(svnStatus.FullPath);
                        continue;
                    }
                }

                if (errorMessage.Length > 0)
                {
                    MessageBox.Show(string.Format(Properties.Resources.ErrorAddFileToSVNFailed, errorMessage.ToString()));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(Utility.TraceException(ex), this.Text);
            }

            this.RefreshListView();
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            StringBuilder errorMessage = new StringBuilder();

            try
            {
                foreach (ListViewItem var in this.listView1.SelectedItems)
                {
                    SvnStatusEventArgs svnStatus = var.Tag as SvnStatusEventArgs;

                    if (svnStatus == null)
                    {
                        continue;
                    }

                    if (Utility.SvnClient.Delete(svnStatus.FullPath) == false)
                    {
                        errorMessage.AppendLine(svnStatus.FullPath);
                        continue;
                    }
                }

                if (errorMessage.Length > 0)
                {
                    MessageBox.Show(string.Format(Properties.Resources.ErrorDeleteFileFromSVNFailed, errorMessage.ToString()), this.Text);
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(Utility.TraceException(ex), this.Text);
            }

            this.RefreshListView();
        }

        private void newChangelistToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string changelistName = string.Empty;

                using (CreateChangelist dlg = new CreateChangelist(this.workPlatform))
                {
                    if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                    {
                        return;
                    }

                    changelistName = dlg.ChangelistName;
                }

                StringBuilder errorMessage = new StringBuilder();
                List<string> newAdds = new List<string>();

                foreach (ListViewItem var in this.listView1.SelectedItems)
                {
                    SvnStatusEventArgs svnStatus = var.Tag as SvnStatusEventArgs;

                    if (svnStatus == null)
                    {
                        continue;
                    }

                    errorMessage.AppendLine(svnStatus.FullPath);
                    newAdds.Add(svnStatus.FullPath);
                }

                if (Utility.SvnClient.AddToChangeList(newAdds, changelistName) == false)
                {
                    MessageBox.Show(string.Format(Properties.Resources.ErrorAddFileToChangelistFailed, changelistName, errorMessage.ToString()), this.Text);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(Utility.TraceException(ex), this.Text);
            }

            this.RefreshListView();
        }

        private void listView1_DoubleClick(object sender, EventArgs e)
        {
            foreach (ListViewItem var in this.listView1.SelectedItems)
            {
                this.OpenDiffFiles(var);
                break;
            }
        }

        private void listView1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode != Keys.Enter)
            {
                return;
            }

            foreach (ListViewItem var in this.listView1.SelectedItems)
            {
                this.OpenDiffFiles(var);
                break;
            }
        }

        private void OpenDiffFiles(ListViewItem var)
        {
            SvnStatusEventArgs svnStatus = var.Tag as SvnStatusEventArgs;

            if (svnStatus == null)
            {
                return;
            }

            if (svnStatus.LocalNodeStatus == SvnStatus.NotVersioned)
            {
                return;
            }

            Process.Start("TortoiseProc.exe", @"/command:diff /path:" + svnStatus.FullPath + " /closeonend:0");
        }

        private void explorerToToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem var in this.listView1.SelectedItems)
            {
                SvnStatusEventArgs svnStatus = var.Tag as SvnStatusEventArgs;

                if (svnStatus == null)
                {
                    return;
                }

                Process.Start("Explorer.exe", Path.GetDirectoryName(svnStatus.FullPath));
                break;
            }
        }
    }
}
